package spl.army.ut;

import static org.junit.Assert.*;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import spl.army.Item;
import spl.army.ItemRequired;
import spl.army.Sergeant;
import spl.army.Warehouse;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.text.ParseException;
import java.util.concurrent.TimeoutException;

public class warehouseTest {
	static final String[] ITEMS = {"sniperRifle", "camouflageSuit", "AK47", "F15"};
	static final int[] AMOUNTS = {30, 30, 500, 30};
	static final Sergeant sergeantDummy = new Sergeant("dummyRambo", "10", "skill0 skill1", "10", "lowestFirst", "4");

	class SimpleReturnThread extends Thread{
		private Item item;
		private int returnTimeout;
		private boolean finished;
		public SimpleReturnThread(Item itemParam, int returnTimeoutParam)
		{
			super();
			this.item = itemParam;
			this.returnTimeout = returnTimeoutParam;
			this.finished = false;
		}
		
		public void run(){
			try {
				Thread.sleep(this.returnTimeout);
			} catch (InterruptedException e) {
				System.out.println("SimpleReturnThread exception");
				//Never fails
			}
			this.item.returnToWarehouse();
			this.finished = true;
		}
		
		public boolean isFinished(){
			return this.finished;
		}
	}
	
	@Before
	public void setUp() throws Exception {
		Warehouse.resetWarehouse();
		for(int i=0;i<ITEMS.length;i++)
		{
			Warehouse.addItem(ITEMS[i], AMOUNTS[i]);
		}
		// Make a warehouse file using ITEMS as above.
	}

	@After
	public void tearDown() throws Exception {
		Warehouse.resetWarehouse();
	}

	
	@Test(timeout=500)
	public void testInitWarehouseFromFile() throws FileNotFoundException, ParseException, IOException {
		Warehouse.resetWarehouse();
		Warehouse.initWarehouseFromFile("resources/test-warehous-file.txt");
		for(int i=0;i<ITEMS.length;i++)
		{
			assertEquals(Warehouse.getItemCurrentAmount(ITEMS[i]), AMOUNTS[i]);
		}		
	}	
	
	@Test(timeout=500)
	public void testGetItem() throws TimeoutException, InterruptedException {
		for(int i=0;i<ITEMS.length;i++)
		{
			assertTrue(Warehouse.getItemCurrentAmount(ITEMS[i]) > 0);
			ItemRequired itmReq = new ItemRequired(ITEMS[i], AMOUNTS[i]);			
			assertNotNull(Warehouse.takeItem(itmReq, sergeantDummy));
			assertTrue(Warehouse.getItemCurrentAmount(ITEMS[i]) == 0);
		}		
	}
	
	@Test(timeout=500)
	public void testGetItemLock() throws InterruptedException, TimeoutException {
		ItemRequired itmReq = new ItemRequired(ITEMS[0], AMOUNTS[0]);
		Item it1 = Warehouse.takeItem(itmReq, sergeantDummy);
		assertNotNull(it1);
		SimpleReturnThread simpleReturnThread = new SimpleReturnThread(it1, 50);
		simpleReturnThread.start();
		assertFalse(simpleReturnThread.finished);
		Thread.sleep(60);
		assertTrue(simpleReturnThread.finished);
	}	
	
	@Test(timeout=500)
	public void testReturnItem() throws TimeoutException, InterruptedException {
		for(int i=0;i<ITEMS.length;i++)
		{
			int firstAmount = Warehouse.getItemCurrentAmount(ITEMS[i]);
			assertTrue(firstAmount > 0);
			ItemRequired itmReq = new ItemRequired(ITEMS[i], 1);
			Item it = Warehouse.takeItem(itmReq, sergeantDummy);
			assertNotNull(it);
			assertTrue(Warehouse.getItemCurrentAmount(ITEMS[i]) == firstAmount-1);
			it.returnToWarehouse();
			assertTrue(Warehouse.getItemCurrentAmount(ITEMS[i]) == firstAmount);
		}		
	}	

	@Test(timeout=500)
	public void testTakeItemAmount() throws TimeoutException, InterruptedException {
		String name = "MyNewRifle";
		Warehouse.addItem(name, 10);
		
		ItemRequired req1 = new ItemRequired(name, 10);
		Item it1 = Warehouse.takeItem(req1, sergeantDummy);
		
		assertEquals(Warehouse.getItemCurrentAmount(name), 0);
		SimpleReturnThread simpleReturnThread = new SimpleReturnThread(it1, 50);
		simpleReturnThread.start();
		
		
		ItemRequired req2 = new ItemRequired(name, 10);
		Item it2 = Warehouse.takeItem(req2, sergeantDummy);
		
		assertEquals(Warehouse.getItemCurrentAmount(name), 0);
		it2.returnToWarehouse();
		assertEquals(Warehouse.getItemCurrentAmount(name), 10);
	}
	
	@Test(timeout=500)
	public void testTakeItemWithItemRequired() throws TimeoutException, InterruptedException {
		String name = "MyNewRifle";
		ItemRequired req = new ItemRequired(name, 10);
		
		Warehouse.addItem(name, 10);
		assertEquals(Warehouse.getItemCurrentAmount(name), 10);
		Item it1 = Warehouse.takeItem(req, sergeantDummy);
		assertEquals(Warehouse.getItemCurrentAmount(name), 0);
		it1.returnToWarehouse();
		assertEquals(Warehouse.getItemCurrentAmount(name), 10);
	}		
	
}
